package com.codyy.felix.webconsole.plugins.route.core;

import com.codyy.felix.webconsole.plugins.route.core.pojo.ProcInfo;
import com.codyy.felix.webconsole.plugins.route.core.pojo.RouteParams;
import com.codyy.felix.webconsole.plugins.route.core.pojo.RouteProgress;
import com.codyy.felix.webconsole.plugins.route.core.pojo.RouteResult;
import org.apache.commons.lang3.StringUtils;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * @author : issac
 * create at:  2019-04-23  14:45
 * @description:
 */
public class ProcessorService {

    private final static String PROC_PREFIX = "codyy-processor-";
    private final static String PROC_SUFFIX = ".jar";
    private final BundleContext bundleContext;

    public ProcessorService(BundleContext bundleContext) {
        this.bundleContext = bundleContext;
    }

    /**
     * 转换器列表
     */
    public RouteProgress list(final RouteParams params) {
        RouteProgress progress = new RouteProgress(params);
        progress.start();
        String queryName = params.getPhrase();
        List<ProcInfo> list = new ArrayList<>();
        Bundle[] bundles = bundleContext.getBundles();
        if (bundles.length <= 0) {
            return progress;
        }
        ProcInfo procInfo = null;
        for (Bundle item : bundles) {
            procInfo = this.convertToProcInfo(item, queryName);
            if (procInfo != null) {
                list.add(procInfo);
            }
        }
        int resultSize = list.size();
        if (params.getResultLimit() >= 1) {
            int limit = params.getResultLimit() >= resultSize ? resultSize : params.getResultLimit();
            list = list.subList(0, limit);
        }
        progress.getResults().addAll(list);
        progress.stop();
        return progress;
    }

    /**
     * 转换单个处理器
     */
    private ProcInfo convertToProcInfo(Bundle bundle, String phrase) {
        String procDesc = Optional.ofNullable(bundle.getHeaders())
                .map(o -> o.get(Constants.BUNDLE_NAME))
                .map(Object::toString)
                .orElse("");
        String procName = bundle.getSymbolicName();

        if (procName.startsWith(PROC_PREFIX) && bundle.getLocation().endsWith(PROC_SUFFIX)) {
            if (StringUtils.isNotBlank(phrase)) {
                if (bundle.getSymbolicName().contains(phrase)) {
                    return new ProcInfo(procName,
                            RouteResult.RouteState.getNameByIndex(bundle.getState()),
                            bundle.getHeaders().get(Constants.BUNDLE_VERSION).toString(),
                            procDesc);
                }
            } else {
                return new ProcInfo(procName,
                        RouteResult.RouteState.getNameByIndex(bundle.getState()),
                        bundle.getHeaders().get(Constants.BUNDLE_VERSION).toString(),
                        procDesc);
            }
        }
        return null;
    }
}
